#pragma once

#include "localsocket.hpp"

namespace Local_TcpSer
{
    using ioserver_t = std::function<void(std::shared_ptr<Local_Sock_Mod::Socket> &sockfd, Local_Inetaddr::Inetaddr &client)>;
    class TcpServer : public NoCopy
    {
    public:
        /************TcpServer*****************/
        TcpServer(uint16_t port, ioserver_t ioserver)
            : _port(port),
              _listensockfd(std::make_shared<Local_Sock_Mod::TcpSocket>()),
              _isrun(false),
              _ioserver(ioserver)
        {
            _listensockfd->ServerTcpMod(_port);
        }
        ~TcpServer() {}
        /************成员函数*****************/
        void start()
        {
            _isrun = true;
            while (1)
            {
                Local_Inetaddr::Inetaddr client;
                auto lo_sockfd = _listensockfd->AcceptCreate(&client);
                if (lo_sockfd == nullptr)
                {
                    continue;
                }
                Local_Log::LOG(Local_Log::LogLever::LINFO) << "accept success";
                // 1.多进程版
                pid_t lo_childid = fork();
                if (lo_childid < 0)
                {
                    Local_Log::LOG(Local_Log::LogLever::LFATAL) << "fork error";
                    exit(ERR_FORK);
                }
                else if (lo_childid == 0)
                {
                    // 子进程
                    _listensockfd->Close();
                    // 孙子进程处理
                    if (fork() > 0)
                    {
                        exit(SUCCESS);
                    }
                    // 处理结果
                    _ioserver(lo_sockfd, client);
                    lo_sockfd->Close();
                    exit(SUCCESS);
                }
                else // if (lo_childid>0)
                {
                    // 父进程
                    lo_sockfd->Close();
                    int ret_wai = waitpid(-1, nullptr, 0);
                    (void)ret_wai;
                }
            }
            _isrun = false;
        }

    private:
        uint16_t _port;
        std::shared_ptr<Local_Sock_Mod::Socket> _listensockfd;
        bool _isrun;
        ioserver_t _ioserver;
    };
}